// @ts-ignore
import Kuroshiro from 'kuroshiro';
// @ts-ignore
import KuromojiAnalyzer from 'kuroshiro-analyzer-kuromoji';
import { SubtitleEntry } from '@/subtitle/store';

const kuroshiro = new Kuroshiro();
const analyzer = new KuromojiAnalyzer({
  dictPath: chrome.runtime.getURL('dict')
});

export const init = async () => {
  await kuroshiro.init(analyzer);
};

// Fisher-Yates (aka Knuth) Shuffle
const shuffle = (originalArray: SubtitleEntry[]) => {
  const array = originalArray.slice(0);
  let currentIndex = array.length,
    randomIndex;

  // While there remain elements to shuffle...
  while (currentIndex != 0) {
    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;

    // And swap it with the current element.
    [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
  }

  return array;
};

export const toFurigana = (text: string) => {
  let str = kuroshiro.convertSync(text, { mode: 'furigana', to: 'hiragana' });
  const sameFuriganaRegex = /<ruby>(.+?)<rp>\(<\/rp><rt>(.+?)<\/rt><rp>/gm;
  const okuriganaRegex = /<ruby>(.+?)<rp>\(<\/rp><rt>(.+?)<\/rt><rp>\)<\/rp><\/ruby>\(.+?\)/gm;
  let newStr = str;
  let arr;
  while ((arr = sameFuriganaRegex.exec(str)) !== null) {
    if (arr.length === 3) {
      if (arr[1] === arr[2]) {
        newStr = newStr.replace(`<ruby>${arr[1]}<rp>(</rp><rt>${arr[1]}</rt><rp>)</rp></ruby>`, arr[1]);
      }
    }
  }
  while ((arr = okuriganaRegex.exec(str)) !== null) {
    if (arr.length === 3) {
      newStr = newStr.replace(`<ruby>${arr[1]}<rp>(</rp><rt>${arr[2].split('<')[0]}</rt><rp>)</rp></ruby>`, arr[1]);
    }
  }
  return newStr;
};

export const formatJapanese = (array: SubtitleEntry[]): SubtitleEntry[] => {
  const selectNum = 20;
  const separator = '\n<br>';
  let selected = shuffle(array).slice(0, selectNum);
  const KanaRegex = /[\u3041-\u3096\u30a1-\u30fa]/g;
  if (!selected.some((e: SubtitleEntry) => e.text.search(KanaRegex) !== -1)) return array;
  const isAssSsa = window.plusSub_subtitle.value.format === '.ass' || window.plusSub_subtitle.value.format === '.ssa';
  const selectedWithLineBreak = selected.filter((e: SubtitleEntry) => e.text.indexOf(separator) !== -1);
  if (!isAssSsa || selectedWithLineBreak.length < selectNum / 2) return array.map((e: SubtitleEntry) => ({ ...e, originalText: e.text, text: toFurigana(e.text) }));
  const isFirstHalfJapanese =
    selectedWithLineBreak.filter(
      (e: SubtitleEntry) => e.text.split(separator).length > 1 && e.text.split(separator)[0].search(KanaRegex) !== -1 && e.text.split(separator).splice(1).join('').search(KanaRegex) === -1
    ).length >
    selectNum / 2;
  // not work well if it has multi-line same language
  if (isFirstHalfJapanese) {
    array.forEach((e: SubtitleEntry) => {
      e.originalText = e.text;
      const splitedText = e.text.split(separator);
      e.text = toFurigana(splitedText[0]) + separator + splitedText.splice(1).join(separator);
    });
  } else {
    array.forEach((e: SubtitleEntry) => {
      e.originalText = e.text;
      const splitedText = e.text.split(separator);
      e.text = splitedText[0] + separator + toFurigana(splitedText.splice(1).join(separator));
    });
  }
  return array;
};
